﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;

namespace CPPEI.Net.TCP
{
    class ReceiveThread
    {
        private Thread _thread;
        private bool _isRunning = false;
        private EventWaitHandle _eventHandle;

        TCPServer _server;

        //private RequestResolver _requestResolver;

        //private RPGHandle _actionDispacher;

        public ReceiveThread(TCPServer server)
        {
            this._server = server;
            //_requestResolver = new RequestResolver();

            //_actionDispacher = new RPGHandle();
        }

        public void Start()
        {
            Console.WriteLine("server start receive");

            this._eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
            this._thread = new Thread(Running);
            this._isRunning = true;
            Console.WriteLine("receive start");
            this._thread.Start();
        }

        public void Stop()
        {
            this._isRunning = false;
            this._eventHandle.WaitOne();
            Console.WriteLine("server stop receive");
        }

        private void Running()
        {
            Console.WriteLine("receive thread start");
            while (_isRunning)
            {
                // client id
                // command
                // mode
                for (int index = 0; index < _server.Data.ClientList.Length; index++)
                {
                    NetClientProxy clientProxy = _server.Data.ClientList[index];
                    if (clientProxy != null && !clientProxy.IsReceiving)
                    {
                        clientProxy.IsReceiving = true;
                        try
                        {
                            clientProxy.Socket.BeginReceive(clientProxy.Buffer, 0, clientProxy.Buffer.Length, SocketFlags.None, new AsyncCallback(OnReceiveCallback), clientProxy);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(string.Format("删除客户端，原因开始接收客户端:{0}数据,出错:{1}", clientProxy.Id, ex));
                            // 移除客户端
                            _server.Data.RemoveClient(clientProxy);
                        }
                    }
                }
            }

            this._eventHandle.Set();
            Console.WriteLine("receive thread stop");
        }

        private void OnReceiveCallback(IAsyncResult ar)
        {
            NetClientProxy proxy = ar.AsyncState as NetClientProxy;
            int receiveLength = 0;

            try
            {
                receiveLength = proxy.Socket.EndReceive(ar);

                proxy.NetBufferPool.AppendBuffer(proxy.Buffer, receiveLength);
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("删除客户端，原因结束接收客户端:{0}数据,出错:{1}", proxy.Id, ex));
                // 移除客户端
                _server.Data.RemoveClient(proxy);

                return;
            }

            //player.ErrorCount = 0;
            if (receiveLength > 0)
            {
                NetPackage netPackage = proxy.NetBufferPool.GetNetBuffer();
                if (netPackage != null)
                {
                    Replay(netPackage, proxy);
                }
            }
            else
            {
                //Log.Error("recv", "收到玩家({0})编号({1})数据长度({2})，视为掉线", player.Client.GetNetAddress(), player.Id, player.ReceiveLength);
                // 收到长度为0的数据视为掉线
                //player.ErrorCount = 1;
            }
            proxy.IsReceiving = false;
        }

        private void Replay(NetPackage netPackage, NetClientProxy proxy)
        {
            NetPackage response = null;
            if (netPackage.PackageType == 0x01)
            {
                // sys package
                if (netPackage.Command == NetSysCommand.Connect)
                {
                    Console.WriteLine("终端请求认证");
                    // 登录认证
                    proxy.IsAuth = true;
                    response = NetPackage.BuildSysPackage(NetSysCommand.Connect, NetReplayMode.Self, proxy.Id, new byte[] { 0x02 });
                }
                else if (netPackage.Command == NetSysCommand.Disconnect)
                {
                    Console.WriteLine("终端请求断开连接");
                    // 断开连接
                    _server.Data.RemoveClient(proxy);
                }
            }
            else
            {
                IRequestHandler handler = _server.RequestFactory.Create(netPackage.Command);
                response = handler.Handle(_server.Data, proxy, netPackage);
            }
            if (netPackage.ReplyMode == NetReplayMode.Self)
            {
                proxy.Send(response);
            }
            else if (netPackage.ReplyMode == NetReplayMode.Room_Other)
            {
                NetRoomData room = _server.Data.GetRoom(proxy.RoomID);
                if (room != null && room.ID == proxy.RoomID)
                {
                    for (int index = 0; index < room.ClientList.Length; index++)
                    {
                        NetClientProxy memberClient = room.ClientList[index];
                        if (memberClient != null
                            && memberClient.IsAuth
                            && memberClient.Id != proxy.Id)
                        {
                            memberClient.Send(response);
                        }
                    }
                }
            }
        }
    }
}
